<?php if (!defined('BASEPATH'))exit('No direct script access allowed');

include_once 'ExceptionDAO.php';
include_once 'TOItem.php';
include_once 'TOAutor.php';
include_once 'TOEditora.php';
include_once 'util/MapError.php';

/**
 * DAO para operações de banco para livro
 * 
 * @author Douglas Rafael
 */
class DAOLivro extends CI_Model {
    var $erro_number;

    /**
     * Lista todos os livros cadastrados.
     * 
     * @param int    $init      Posição inicial do cursor
     * @param int    $quant     Total de registros
     * @param string $orderby   Nome da coluna a ser ordenada
     * @param string $direction Direção: ASC ou DESC
     * @return array TOItem    Array de objetos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function select_all_book($init, $quant) {
        try {
            $this->db->select('item.codigo, item.isbn, item.titulo, item.subtitulo, item.titulo_original, item.edicao, item.ano, item.total_paginas,
                item.descricao as descricao_livro, item.localizacao, item.imagem, item.data_cadastro, item.item_tipo_id, item.editora_id, t.nome AS tipo_nome, e.nome AS editora_nome');
            $this->db->join('item_tipo t', 't.id = item_tipo_id');
            $this->db->join('editora e', 'e.id = item.editora_id');
            $this->db->where('item.item_tipo_id', TOItem::TIPO_BOOK);
            $this->db->order_by('item.codigo', 'DESC');
            $result = $this->db->get('item', $quant, $init);
            
            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar os livros.');
            } else {
                //Carregando models necessários
                $this->load->model(array('DAOCategoria', 'DAOAutor'));
                $livros = array();
                foreach ($result->result() as $value) {
                    $item = new TOItem();
                    $item->codigo = $value->codigo;
                    $item->titulo = $value->titulo;
                    $item->subtitulo = $value->subtitulo;
                    $item->descricao = $value->descricao_livro;
                    $item->localizacao = $value->localizacao;
                    $item->imagem = $value->imagem;
                    $item->data_cadastro = $value->data_cadastro;
                    
                    $item->livro = new TOLivro();
                    $item->livro->isbn = $value->isbn;
                    $item->livro->titulo_original = $value->titulo_original;
                    $item->livro->edicao = $value->edicao;
                    $item->livro->ano = $value->ano;
                    $item->livro->total_paginas = $value->total_paginas;

                    $item->tipo = new TOTipo();
                    $item->tipo->id = $value->item_tipo_id;
                    $item->tipo->nome = $value->tipo_nome;

                    $item->livro->editora = new TOEditora();
                    $item->livro->editora->id = $value->editora_id;
                    $item->livro->editora->nome = $value->editora_nome;

                    // Autores do Item
                    $item->livro->autores = $this->DAOAutor->get_authors_item($item->codigo);
                    
                    // Categorias do Item
                    $item->categorias = $this->DAOCategoria->get_categories_item($item->codigo);
                    

                    array_push($livros, $item);
                }
                return $livros;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Retorna o Total geral de livros cadastrados.
     * 
     * @return int Total de resgistros
     */
    public function amount_all_books() {
        $this->db->where('item_tipo_id', TOItem::TIPO_BOOK);
        return $this->db->count_all_results('item');
    }
    
    
    /**
     * Retorna o livro de acordo com o seu código
     * 
     * @param TOItem $item
     * @return \TOItem
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_book(TOItem $item) {
        try {
            $this->db->select('item.codigo, item.isbn, item.titulo, item.subtitulo, item.titulo_original, item.edicao, item.ano, item.total_paginas,
                item.descricao as descricao_livro, item.localizacao, item.imagem, item.data_cadastro, item.item_tipo_id, item.editora_id, item.usuario_admin_id,
                t.nome AS tipo_nome, e.nome AS editora_nome, item.idioma');
            $this->db->join('item_tipo t', 't.id = item_tipo_id');
            $this->db->join('editora e', 'e.id = item.editora_id');
            $this->db->where('item.item_tipo_id', TOItem::TIPO_BOOK);
            $this->db->where('codigo', $item->codigo);
            $result = $this->db->get('item');
            
            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar selecionar o livro.');
            } else {
                $value = $result->row();

                $item = new TOItem();
                $item->codigo = $value->codigo;
                $item->titulo = $value->titulo;
                $item->subtitulo = $value->subtitulo;
                $item->descricao = $value->descricao_livro;
                $item->localizacao = $value->localizacao;
                $item->imagem = $value->imagem;
                $item->data_cadastro = $value->data_cadastro;
                $item->idioma = $value->idioma;

                $item->livro = new TOLivro();
                $item->livro->isbn = $value->isbn;
                $item->livro->titulo_original = $value->titulo_original;
                $item->livro->edicao = $value->edicao;
                $item->livro->ano = $value->ano;
                $item->livro->total_paginas = $value->total_paginas;

                $item->tipo = new TOTipo();
                $item->tipo->id = $value->item_tipo_id;
                $item->tipo->nome = $value->tipo_nome;

                $item->livro->editora = new TOEditora();
                $item->livro->editora->id = $value->editora_id;
                $item->livro->editora->nome = $value->editora_nome;

                // Autores do Item
                $this->load->model('DAOAutor');
                $item->livro->autores = $this->DAOAutor->get_authors_item($item->codigo);
                
                // Categorias do Item
                $this->load->model('DAOCategoria');
                $item->categorias = $this->DAOCategoria->get_categories_item($item->codigo);

                // Movimentação do Item
                $this->load->model('DAOMovimentacao');
                $item->movimentacao = $this->DAOMovimentacao->get_movimentacao_item($item->codigo);

                // Usuario Admin que cadastrou o item
                $this->load->model('DAOUsuario');
                $item->admin = $this->DAOUsuario->get_user($value->usuario_admin_id);

                return $item;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    

    /**
     * Seleciona um livro de acordo com seu código
     * 
     * @param  TOItem $item
     * @return TOItem Item selecionado
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_book_json(TOItem $item) {
        try {
            $this->db->select('item.codigo, item.isbn, item.titulo, item.subtitulo, item.titulo_original, item.edicao, item.ano, item.total_paginas,
                item.descricao as descricao_livro, item.localizacao, item.imagem, item.data_cadastro, item.item_tipo_id, item.editora_id, item.usuario_admin_id,
                t.nome AS tipo_nome, e.nome AS editora_nome, item.idioma');
            $this->db->join('item_tipo t', 't.id = item_tipo_id');
            $this->db->join('editora e', 'e.id = item.editora_id');
            $this->db->where('item.item_tipo_id', TOItem::TIPO_BOOK);
            $this->db->where("codigo", $item->codigo);
            $result = $this->db->get('item');

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar selecionar o livro.');
            } else {
                $value = $result->row();
                if (count($value) > 0) {
                    $item = new TOItem();
                    $item->codigo = $value->codigo;
                    $item->titulo = $value->titulo;
                    $item->subtitulo = $value->subtitulo;
                    $item->descricao = $value->descricao_livro;
                    $item->localizacao = $value->localizacao;
                    $item->imagem = $value->imagem;
                    $item->data_cadastro = $value->data_cadastro;
                    $item->idioma = $value->idioma;

                    $item->livro = new TOLivro();
                    $item->livro->isbn = $value->isbn;
                    $item->livro->titulo_original = $value->titulo_original;
                    $item->livro->edicao = $value->edicao;
                    $item->livro->ano = $value->ano;
                    $item->livro->total_paginas = $value->total_paginas;

                    $item->tipo = new TOTipo();
                    $item->tipo->id = $value->item_tipo_id;
                    $item->tipo->nome = $value->tipo_nome;

                    $item->livro->editora = new TOEditora();
                    $item->livro->editora->id = $value->editora_id;
                    $item->livro->editora->nome = $value->editora_nome;

                    // Autores do item
                    $this->load->model('DAOAutor');
                    $item->livro->autores = $this->DAOAutor->get_authors_item($value->codigo);

                    // Categorias do item
                    $this->load->model('DAOCategoria');
                    $item->categorias = $this->DAOCategoria->get_categories_item($value->codigo);

                    // Movimentação do Item
                    $this->load->model('DAOMovimentacao');
                    $item->movimentacao = $this->DAOMovimentacao->get_movimentacao_item($item->codigo);

                    // Emprestimos do item
                    $this->load->model('DAOEmprestimo');
                    $item->emprestimos = $this->DAOEmprestimo->get_loans_item($item->codigo, 0, 5);

                    // Usuario Admin que cadastrou o item
                    $this->load->model('DAOUsuario');
                    $item->admin = $this->DAOUsuario->get_user($value->usuario_admin_id);
                } else {
                    $item = NULL;
                }

                return $item;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Insere livro
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_book(TOItem $item) {
        try {
            $this->db->trans_start();

            $this->db->set('isbn', $item->livro->isbn);
            $this->db->set('titulo', $item->titulo);
            $this->db->set('subtitulo', $item->subtitulo);
            $this->db->set('titulo_original', $item->livro->titulo_original);
            $this->db->set('edicao', $item->livro->edicao);
            $this->db->set('ano', $item->livro->ano);
            $this->db->set('total_paginas', $item->livro->total_paginas);
            $this->db->set('descricao', $item->descricao);
            $this->db->set('idioma', $item->idioma);
            $this->db->set('localizacao', $item->localizacao);
            $this->db->set('imagem', $item->imagem);
            $this->db->set('data_cadastro', $item->data_cadastro);
            $this->db->set('usuario_admin_id', $item->admin->id);
            $this->db->set('item_tipo_id', $item->tipo->id);
            $this->db->set('editora_id', $item->livro->editora->id);
            
            $result = $this->db->insert('item');
            
            //cerifica se ocorreu tudo bem no insert do livro
            if (!$result) {
                //Pegando numero do erro
                $this->db->_error_number() ? $this->erro_number = $this->db->_error_number() : '';
                throw new Exception();
            } else {
                $item->codigo = $this->db->insert_id(); // Pegendo o id do item inserido
                //INSERIR autores
                $this->load->model('DAOAutor');
                $this->DAOAutor->insert_authors_item($item);
                
                //INSERIR categorias
                $this->load->model('DAOCategoria');
                $this->DAOCategoria->insert_category_item($item);

                //INSERIR movimentacao
                $this->load->model('DAOMovimentacao');
                $this->DAOMovimentacao->insert_movimentacao($item);

                $this->db->trans_complete();

                if ($this->db->trans_status() === FALSE) {
                    throw new Exception('Ocorreu um erro de banco de dados ao tentar inserir o item.');
                }
            }
        } catch (Exception $e) {
            //Se foi feito o upload da imagem. A mesma é deletada
            if(!empty($item->imagem) && $item->imagem != $this->config->item('img_upload_default')){
                $this->UploadImage->delete_image($this->config->item('path_img_item') . 'book/', $item->imagem);
            }
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            if(isset($this->erro_number)){
                 throw new ExceptionDAO($erro->getError($this->erro_number, NULL, $item->titulo));
            }else{
                 throw new ExceptionDAO($e->getMessage());
            }
        }
    }

    /**
     * Atualiza dados do livro
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_book(TOItem $item) {
        try {
            $this->db->trans_start();

            $this->db->set('isbn', $item->livro->isbn);
            $this->db->set('titulo', $item->titulo);
            $this->db->set('subtitulo', $item->subtitulo);
            $this->db->set('titulo_original', $item->livro->titulo_original);
            $this->db->set('edicao', $item->livro->edicao);
            $this->db->set('ano', $item->livro->ano);
            $this->db->set('total_paginas', $item->livro->total_paginas);
            $this->db->set('descricao', $item->descricao);
            $this->db->set('idioma', $item->idioma);
            $this->db->set('localizacao', $item->localizacao);
            $item->imagem != NULL ? $this->db->set('imagem', $item->imagem) : ''; // Verifica se a imagem foi atualizada
            $this->db->set('editora_id', $item->livro->editora->id);
            $this->db->where('codigo', $item->codigo);
            
            $result = $this->db->update('item');
            
            //cerifica se ocorreu tudo bem no insert do livro
            if (!$result) {
                //Pegando numero do erro
                $this->db->_error_number() ? $this->erro_number = $this->db->_error_number() : '';
                throw new Exception();
            } else {
                //INSERIR autores
                $this->load->model('DAOAutor');
                $this->DAOAutor->update_authors_item($item);
                
                //INSERIR categorias
                $this->load->model('DAOCategoria');
                $this->DAOCategoria->update_category_item($item);

                //INSERIR movimentacao
                $this->load->model('DAOMovimentacao');
                $this->DAOMovimentacao->update_movimentacao($item);

                $this->db->trans_complete();

                if ($this->db->trans_status() === FALSE) {
                    throw new Exception('Ocorreu um erro de banco de dados ao tentar atualizar o item.');
                }
            }
        } catch (Exception $e) {
            //Se foi feito o upload da imagem. A mesma é deletada
            if(!empty($item->imagem)){
                $this->Upload_image->delete_image($this->config->item('path_img_item') . 'book/', $item->imagem);
            }
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            if(isset($this->erro_number)){
                 throw new ExceptionDAO($erro->getError($this->erro_number, NULL, $item->titulo));
            }else{
                 throw new ExceptionDAO($e->getMessage());
            }
        }
    }

    /**
     * Excluir livro de acordo com o id.
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO 
     */
    public function delete_book(TOItem $item) {
        try {
            $this->db->where('codigo', $item->codigo);
            $result = $this->db->delete('item');
            if (!$result) {
                throw new Exception();
            } else {
                if (!empty($item->imagem)) {
                    $this->load->model('UploadImage');
                    $this->UploadImage->delete_image($this->config->item('path_img_item') . 'book/', $item->imagem);
                }
            }
        } catch (Exception $e) {
            $erro = new MapError();
            throw new ExceptionDAO($erro->getError($this->db->_error_number(), $this->db->_error_message(), $item->titulo));
        }
    }

    /**
     * Efetua Busca por autor.
     * 
     * @param int $init         Ponto Inicial do cursor no select
     * @param int $quant        Quantidade limite que deverá retornar o select
     * @param string $term      Termo a ser buscado
     * @return array TOItem     Array contendo os itens
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function search_book($init, $quant, $term = NULL) {
        try {
            $this->db->select('item.codigo, item.isbn, item.titulo, item.subtitulo, item.titulo_original, item.edicao, item.ano, item.total_paginas,
                item.descricao as descricao_livro, item.localizacao, item.imagem, item.data_cadastro, item.item_tipo_id, item.editora_id, item.usuario_admin_id,
                t.nome AS tipo_nome, e.nome AS editora_nome, item.idioma');
            $this->db->join('item_tipo t', 't.id = item_tipo_id');
            $this->db->join('autor_has_item ai', 'ai.item_codigo = item.codigo', 'LEFT');
            $this->db->join('autor a', 'ai.autor_id = a.id' , 'LEFT');
            $this->db->join('editora e', 'e.id = item.editora_id');
            $this->db->join('categoria_has_item ci', 'ci.item_codigo = item.codigo', 'LEFT');
            $this->db->join('categoria c', 'ci.categoria_id = c.id' , 'LEFT');
            $this->db->where('(item.item_tipo_id = ' . TOItem::TIPO_BOOK . ')');
            $this->db->where("(item.codigo LIKE '%" . $term . "%' OR item.titulo LIKE '%" . $term . "%' OR a.nome LIKE '%" . $term . "%' OR e.nome LIKE '%" . $term . "%' OR c.nome LIKE '%" . $term . "%')");
            $this->db->group_by('item.codigo', 'ASC');
            $this->db->order_by('item.codigo', 'ASC');
            $result = $this->db->get('item', $quant, $init);
            
            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar efetuar busca por livros.');
            } else {
                //Carregando models necessários
                $this->load->model(array('DAOCategoria', 'DAOAutor'));
                $livros = array();
                if ($result) {
                    foreach ($result->result() as $value) {
                        $item = new TOItem();
                        $item->codigo = $value->codigo;
                        $item->titulo = $value->titulo;
                        $item->subtitulo = $value->subtitulo;
                        $item->descricao = $value->descricao_livro;
                        $item->localizacao = $value->localizacao;
                        $item->imagem = $value->imagem;
                        $item->idioma = $value->idioma;

                        $item->livro = new TOLivro();
                        $item->livro->isbn = $value->isbn;
                        $item->livro->titulo_original = $value->titulo_original;
                        $item->livro->edicao = $value->edicao;
                        $item->livro->ano = $value->ano;
                        $item->livro->total_paginas = $value->total_paginas;

                        $item->tipo = new TOTipo();
                        $item->tipo->id = $value->item_tipo_id;
                        $item->tipo->nome = $value->tipo_nome;

                        $item->livro->editora = new TOEditora();
                        $item->livro->editora->id = $value->editora_id;
                        $item->livro->editora->nome = $value->editora_nome;

                        // Autores do Item
                        $item->livro->autores = $this->DAOAutor->get_authors_item($item->codigo);

                        // Categorias do item
                        $item->categorias = $this->DAOCategoria->get_categories_item($item->codigo);

                        array_push($livros, $item);
                    }
                }
                return $livros;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Retorna a quantidade de registros da busca
     * 
     * @param string $term Termo a ser buscado
     * @return int
     */
    public function amount_search_book($term) {
        $this->db->join('item_tipo t', 't.id = item_tipo_id');
        $this->db->join('autor_has_item ai', 'ai.item_codigo = item.codigo', 'LEFT');
        $this->db->join('autor a', 'ai.autor_id = a.id', 'LEFT');
        $this->db->join('editora e', 'e.id = item.editora_id');
        $this->db->join('categoria_has_item ci', 'ci.item_codigo = item.codigo', 'LEFT');
        $this->db->join('categoria c', 'ci.categoria_id = c.id', 'LEFT');
        $this->db->where('(item.item_tipo_id = ' . TOItem::TIPO_BOOK . ')');
        $this->db->where("(item.codigo LIKE '%" . $term . "%' OR item.titulo LIKE '%" . $term . "%' OR a.nome LIKE '%" . $term . "%' OR e.nome LIKE '%" . $term . "%' OR c.nome LIKE '%" . $term . "%')");
        $this->db->group_by('item.codigo', 'ASC');
        $result = $this->db->get('item');

        return count($result->result());
    }

}